case
and condp
In Clojure, both case
and condp
are used to handle conditional branching, but they have different use cases and are particularly useful for handling complex conditions. case
is suitable for simple value-based matches, while condp
allows more flexibility with complex predicates. Here’s a detailed look at how to use both in scenarios requiring more complex conditions.
case
for Simple Value-Based MatchingThe case
expression in Clojure performs conditional branching based on exact matches for specific values. It is optimized for performance but does not support complex predicates or ranges.
case
for Matching Specific Values(defn describe-grade [grade]
(case grade
"A" "Excellent"
"B" "Good"
"C" "Average"
"D" "Below Average"
"F" "Fail"
"Unknown grade"))
(describe-grade "A") ; Output: "Excellent"
(describe-grade "E") ; Output: "Unknown grade"
In this example, case
is ideal because each grade corresponds to an exact match. However, it is limited in cases where you need to evaluate complex conditions (e.g., ranges, comparisons). For such cases, condp
is more flexible.
condp
for Complex Condition MatchingThe condp
macro is more flexible than case
because it allows you to specify a predicate function and compare each value with the predicate. This is particularly useful when you have multiple conditions that aren’t based on simple value matches, such as ranges or other conditions requiring functions.
condp
(condp predicate test-expr
value1 result1
value2 result2
...
:else default-result)
Here, predicate
is the function applied to test-expr
and each value
. If the predicate returns true, the corresponding result is executed.
condp
for RangesSuppose we want to categorize age ranges:
(defn age-category [age]
(condp <= age
13 "Child"
18 "Teenager"
65 "Adult"
"Senior"))
(age-category 10) ; Output: "Child"
(age-category 15) ; Output: "Teenager"
(age-category 40) ; Output: "Adult"
(age-category 70) ; Output: "Senior"
Here, the <=
predicate compares age
against each boundary. If age
is less than or equal to 13, it’s a "Child". If age
is greater than 13 but less than or equal to 18, it’s a "Teenager", and so on.
condp
with Custom ConditionsWe can also use condp
with a custom predicate, such as contains?
for checking if a value is part of a set:
(defn animal-type [animal]
(condp contains? animal
#{"dog" "cat" "hamster"} "Pet"
#{"lion" "tiger" "bear"} "Wild Animal"
#{"chicken" "cow" "goat"} "Farm Animal"
"Unknown"))
(animal-type "dog") ; Output: "Pet"
(animal-type "lion") ; Output: "Wild Animal"
(animal-type "chicken") ; Output: "Farm Animal"
(animal-type "whale") ; Output: "Unknown"
In this example, condp
with contains?
helps us group animals into categories based on set membership.
case
and condp
Feature | case | condp |
---|---|---|
Usage | Simple, exact matches | Complex conditions, predicates |
Best For | Value-based cases, enums | Ranges, sets, custom conditions |
Limitations | No complex conditions, only exact matches | Slightly less performant, but flexible |
case
is ideal for simple value-based matches where each condition is an exact value.condp
is highly flexible and suitable for complex conditions, ranges, and other predicate-based comparisons.Both case
and condp
help manage complex conditional logic in Clojure and make code more readable and efficient by avoiding nested if
and cond
statements.
common.read_more